using System;
using System.Collections.Generic;
using UnityEngine;

namespace EchoFramework
{
    /// <summary>
    /// UIViewBase基类
    /// </summary>
    [RequireComponent(typeof(CanvasGroup))]
    [RequireComponent(typeof(PrefabBinder))]
    public class UIViewBase : MonoBehaviour
    {
        protected CanvasGroup canvasGroup;
        protected PrefabBinder prefabBinder;

        /// <summary>
        /// 当前界面的事件字典
        /// </summary>
        private Dictionary<int, Action<EventObject>> eventDict = new Dictionary<int, Action<EventObject>>();

        /// <summary>
        /// 当前界面的Dispatcher列表
        /// </summary>
        private List<Dispatcher> dispatcherList = new List<Dispatcher>();

        /// <summary>
        /// 该界面是否是显示状态
        /// </summary>
        public bool IsShow
        {
            get;
            private set;
        }
        /// <summary>
        /// 界面ID
        /// </summary>
        public int ViewID => (int)ViewCfg.ViewID;
        /// <summary>
        /// 界面配置表
        /// </summary>
        public UIViewCfg ViewCfg { get; private set; }

        /// <summary>
        /// 打开界面时调用 在OnStart之前
        /// </summary>
        public virtual void OnAwake()
        {
            canvasGroup = GetComponent<CanvasGroup>();
            prefabBinder = GetComponent<PrefabBinder>();
            canvasGroup.alpha = 1;
            canvasGroup.blocksRaycasts = true;
            IsShow = true;
        }

        /// <summary>
        /// 打开界面时调用
        /// </summary>
        public virtual void OnStart(params object[] objs)
        {
            
        }

        /// <summary>
        /// 界面打开时每帧调用
        /// </summary>
        public virtual void OnUpdate()
        {

        }

        /// <summary>
        /// 界面关闭时调用
        /// </summary>
        public virtual void OnClose()
        {
            Destroy(gameObject);
            IsShow = false;
            UnRegisterUIEvent(); //清空当前界面所有事件
            RelaseDispatcherList();  //清空当前界面所有Dispatcher
        }

        /// <summary>
        /// 设置界面显示
        /// </summary>
        public void SetViewShow()
        {
            IsShow = true;
            canvasGroup.alpha = 1;
            canvasGroup.blocksRaycasts = true;
        }

        /// <summary>
        /// 设置界面隐藏
        /// </summary>
        public void SetViewHide()
        {
            IsShow = false;
            canvasGroup.alpha = 0;
            canvasGroup.blocksRaycasts = false;
        }

        /// <summary>
        /// 设置界面配置表
        /// </summary>
        public void SetViewConfig(UIViewCfg cfg)
        {
            ViewCfg = cfg;
        }

        /// <summary>
        /// 关闭界面
        /// </summary>
        public void CloseWindow()
        {
            if(ViewCfg.PanelType== UIPanelType.WindowPanel || ViewCfg.PanelType == UIPanelType.FloatPanel)
            {
                OnClose();
            }
            else
            {
                UIViewManager.Instance.CloseWindow(ViewID);
            }
        }

        /// <summary>
        /// 注册界面事件，实际调用的也是EventManager,只是将取消注册自动调用在了OnClose中
        /// </summary>
        /// <param name="eventType">事件类型</param>
        /// <param name="eventAction">Action</param>
        protected void RegisterUIEvent(EventType eventType, Action<EventObject> eventAction)
        {
            RegisterUIEvent((int)eventType, eventAction);
        }

        /// <summary>
        /// 注册界面事件，实际调用的也是EventManager,只是将取消注册自动调用在了OnClose中
        /// </summary>
        /// <param name="eventType">事件类型</param>
        /// <param name="eventAction">Action</param>
        protected void RegisterUIEvent(int eventType, Action<EventObject> eventAction)
        {
            if(!eventDict.ContainsKey(eventType))
            {
                eventDict[eventType] = eventAction;
                EventManager.Instance.Register(eventType, eventAction);
            }
            else
            {
                GameLogger.LogWarning($"界面：{ViewID} 已注册过事件{eventType}");
            }
        }

        /// <summary>
        /// 清空界面事件
        /// </summary>
        private void UnRegisterUIEvent()
        {
            if (eventDict == null)
                return;
             
            Dictionary<int, Action<EventObject>>.Enumerator iter = eventDict.GetEnumerator();
            while (iter.MoveNext())
            {
                EventManager.Instance.UnRegiseter(iter.Current.Key, iter.Current.Value);
            }
            iter.Dispose();
            eventDict.Clear();
        }
        
        /// <summary>
        /// 延迟时间调用(单位：秒)
        /// </summary>
        /// <param name="delayTime">延迟多少时间</param>
        /// <param name="action">行为</param>
        protected void DelaySeconed(float delayTime, Action action)
        {
            Dispatcher dispatcher = TimeManager.Instance.DelaySeconed(delayTime, action);
            dispatcherList.Add(dispatcher);
        }
        
        /// <summary>
        /// 延迟1秒后调用
        /// </summary>
        /// <param name="action">行为</param>
        protected void DelayOneSeconed(Action action)
        {
            Dispatcher dispatcher = TimeManager.Instance.DelayOneSeconed(action);
            dispatcherList.Add(dispatcher);
        }
        
        /// <summary>
        /// 延迟帧数调用(单位：帧)
        /// </summary>
        /// <param name="delayFrame">延迟多少帧数</param>
        /// <param name="action">行为</param>
        /// <returns>返回分发对象</returns>
        protected void DelayFrame(int delayFrame, Action action)
        {
            Dispatcher dispatcher = TimeManager.Instance.DelayFrame(delayFrame, action);
            dispatcherList.Add(dispatcher);
        }
        
        /// <summary>
        /// 延迟1帧后调用
        /// </summary>
        /// <param name="action">行为</param>
        /// <returns>返回分发对象</returns>
        protected void DelayOneFrame(Action action)
        {
            Dispatcher dispatcher = TimeManager.Instance.DelayOneFrame(action);
            dispatcherList.Add(dispatcher);
        }

        /// <summary>
        /// 清空当前界面的所有Dispatcher对象
        /// </summary>
        private void RelaseDispatcherList()
        {
            foreach (Dispatcher dispatcher in dispatcherList)
            {
                dispatcher?.Reset();
            }
        }
    }
}